package com.lap.context.starter.tools;

import com.lap.framework.crypto.EncodeUtil;
import jakarta.servlet.http.HttpServletRequest;
import java.util.function.Function;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
@UtilityClass
public class HttpRequestUtil {

  /**
   * 通用获取值方法，优先从 Header 中获取，空则从 Attribute 中获取
   *
   * @param request HttpServletRequest
   * @param key 请求头或属性的 key
   * @param converter 字符串转换函数，如 Integer::valueOf
   * @param decode 是否先解码
   * @param <T> 返回值类型
   * @return 转换后的值或 null
   */
  public static <T> T getValue(
      HttpServletRequest request, String key, Function<String, T> converter, boolean decode) {
    if (StringUtils.isBlank(key)) {
      return null;
    }

    String originValue = request.getHeader(key);
    if (StringUtils.isBlank(originValue)) {
      originValue = (String) request.getAttribute(key);
    }

    if (StringUtils.isBlank(originValue)) {
      return null;
    }

    if (decode) {
      originValue = EncodeUtil.decode(originValue);
    }

    try {
      return converter.apply(originValue);
    } catch (Exception e) {
      log.warn("Header key [ {} ] value [ {} ] conversion failed", key, originValue);
      return null;
    }
  }

  /** 获取字符串值 */
  public static String getString(HttpServletRequest request, String key) {
    return getString(request, key, false);
  }

  /** 获取字符串值（可解码） */
  public static String getString(HttpServletRequest request, String key, boolean decode) {
    return getValue(request, key, Function.identity(), decode);
  }

  /** 获取整数值 */
  public static Integer getInteger(HttpServletRequest request, String key) {
    return getValue(request, key, Integer::valueOf, false);
  }

  /** 获取长整型值 */
  public static Long getLong(HttpServletRequest request, String key) {
    return getValue(request, key, Long::valueOf, false);
  }

  /** 获取布尔值 */
  public static Boolean getBoolean(HttpServletRequest request, String key) {
    return getValue(request, key, Boolean::valueOf, false);
  }
}
